package com.empire.module.member.controller.admin.user;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import com.empire.framework.common.pojo.CommonResult;
import com.empire.framework.common.pojo.PageResult;
import com.empire.framework.common.util.date.LocalDateTimeUtils;
import com.empire.framework.excel.core.util.ExcelUtils;
import com.empire.module.member.controller.admin.user.vo.*;
import com.empire.module.member.convert.user.MemberUserConvert;
import com.empire.module.member.dal.dataobject.group.MemberGroupDO;
import com.empire.module.member.dal.dataobject.locationlast.LocationLastDO;
import com.empire.module.member.dal.dataobject.tag.MemberTagDO;
import com.empire.module.member.dal.dataobject.user.MemberUserDO;
import com.empire.module.member.dal.dataobject.warningindividual.PersonWarningCountDTO;
import com.empire.module.member.service.casepersonrelation.CasePersonRelationService;
import com.empire.module.member.service.group.MemberGroupService;
import com.empire.module.member.service.locationlast.LocationLastService;
import com.empire.module.member.service.presentation.PresentationService;
import com.empire.module.member.service.presentationpersonrelation.PresentationPersonRelationService;
import com.empire.module.member.service.tag.MemberTagService;
import com.empire.module.member.service.user.MemberUserService;
import com.empire.module.member.service.warnconfigpersonrelation.WarnConfigPersonRelationService;
import com.empire.module.member.service.warningindividual.WarningIndividualService;
import com.empire.module.system.enums.common.SexEnum;
import com.empire.module.system.enums.common.YesNoEnum;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.empire.framework.common.pojo.CommonResult.success;
import static com.empire.framework.common.util.collection.CollectionUtils.convertSet;

@Tag(name = "管理后台 - 会员用户")
@RestController
@RequestMapping("/member/user")
@Validated
public class MemberUserController {

    @Resource
    private MemberUserService memberUserService;
    @Resource
    private MemberTagService memberTagService;
    @Resource
    private MemberGroupService memberGroupService;
    @Resource
    private CasePersonRelationService casePersonRelationService;
    @Resource
    private PresentationPersonRelationService presentationPersonRelationService;
    @Resource
    private WarnConfigPersonRelationService warnConfigPersonRelationService;
    @Resource
    private LocationLastService locationLastService;
    @Resource
    private WarningIndividualService warningIndividualService;

    @PostMapping("/create")
    @Operation(summary = "新建人员")
    @PreAuthorize("@ss.hasPermission('member:user:create')")
    public CommonResult<Long> createUser(@Valid @RequestBody MemberUserSaveReqVO createReqVO) {
        return success(memberUserService.createUser(createReqVO));
    }

    @PutMapping("/update")
    @Operation(summary = "更新人员")
    @PreAuthorize("@ss.hasPermission('member:user:update')")
    public CommonResult<Boolean> updateUser(@Valid @RequestBody MemberUserUpdateReqVO updateReqVO) {
        memberUserService.updateUser(updateReqVO);
        return success(true);
    }

    @PutMapping("/bindDeptMember")
    @Operation(summary = "绑定会员部门关系")
    @PreAuthorize("@ss.hasPermission('member:divide:dept')")
    public CommonResult<Boolean> bindDeptMember(@Valid @RequestBody DeptMemberUserUpdateReqVO updateReqVO) {
        memberUserService.bindDeptMember(updateReqVO);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得人员信息")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('person:user:query')")
    public CommonResult<MemberUserRespVO> getUser(@RequestParam("id") Long id) {
        MemberUserDO user = memberUserService.getUser(id);
        MemberUserRespVO memberUserRespVO = MemberUserConvert.INSTANCE.convert03(user);

        // 处理用户标签返显
        Set<Long> tagIds = user.getTagIds() != null ? new HashSet<>(user.getTagIds()) : new HashSet<>();
        List<MemberTagDO> tags = memberTagService.getTagList(tagIds);

        // 处理人员分类返显
        List<MemberGroupDO> groups = new ArrayList<>();
        if (user.getGroupId() != null) {
            groups = Collections.singletonList(memberGroupService.getGroup(user.getGroupId()));
        }

        MemberUserConvert.INSTANCE.convert2FullVo(memberUserRespVO, tags, groups);

        // 补充最后位置
        LocationLastDO locationLastDO = locationLastService.getLocationLast(user.getId());
        if (locationLastDO != null) {
            memberUserRespVO.setFrequentAddress(locationLastDO.getFrequentAddress());
            memberUserRespVO.setAppearanceCount(locationLastDO.getAppearanceCount());
            memberUserRespVO.setLastLocationTime(LocalDateTimeUtil.format(locationLastDO.getLocationTime(),
                    "yyyy-MM-dd HH:mm:ss"));
            memberUserRespVO.setLastLocation(locationLastDO.getAddress());

        }
        return success(memberUserRespVO);
    }

    @GetMapping("/getByIdCard")
    @Operation(summary = "通过证件号码获得人员信息")
    @Parameter(name = "idcard", description = "证件号码", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('person:user:query')")
    public CommonResult<MemberUserRespVO> getByIdCard(@RequestParam(value = "idcard") String idcard) {
        MemberUserDO user = memberUserService.getByIdCard(idcard);
        return success(MemberUserConvert.INSTANCE.convert03(user));
    }

    @GetMapping("/page")
    @Operation(summary = "获得人员分页")
    @PreAuthorize("@ss.hasPermission('person:user:query')")
    public CommonResult<PageResult<MemberUserRespVO>> getUserPage(@Valid MemberUserPageReqVO pageVO) {
        // 获取案件关联人员ID集合
        Set<Long> casePersonIdSet = getCasePersonIds(pageVO.getCaseId());
        // 获取预警关联人员ID集合
        Set<Long> warnPersonIdSet = getWarnConfigPersonIds(pageVO.getWarnConfigId());

        // 查询分页数据并处理标签/分组
        PageResult<MemberUserRespVO> voPageResult = getProcessedPageResult(pageVO, casePersonIdSet, warnPersonIdSet);

        // 同时设置案件和预警关联标志
        voPageResult.getList().forEach(vo -> {
            vo.setIsCase(casePersonIdSet.contains(vo.getId()));
            vo.setIsWarnSetting(warnPersonIdSet.contains(vo.getId()));
        });

        return success(voPageResult);
    }

    @GetMapping("/casePage")
    @Operation(summary = "获得案件人员分页")
    @PreAuthorize("@ss.hasPermission('person:user:query')")
    public CommonResult<PageResult<MemberUserRespVO>> getCaseUserPage(@Valid MemberUserPageReqVO pageVO) {
        // 获取案件关联人员ID集合
        Set<Long> casePersonIdSet = getCasePersonIds(pageVO.getCaseId());
        // 当"只看已选"且有数据时，限制查询ID列表并判断是否需要查询
        if (pageVO.getOnlyWarn()) {
            if (casePersonIdSet.isEmpty()) {
                return success(PageResult.empty());
            }
            pageVO.setIdList(new ArrayList<>(casePersonIdSet));
        }
        // 查询分页数据并处理标签/分组
        PageResult<MemberUserRespVO> voPageResult = getProcessedPageResult(pageVO, casePersonIdSet, Collections.emptySet());

        // 设置案件关联标志
        voPageResult.getList().forEach(vo -> vo.setIsCase(casePersonIdSet.contains(vo.getId())));

        return success(voPageResult);
    }

    @GetMapping("/presentationPage")
    @Operation(summary = "获得案件人员分页")
    @PreAuthorize("@ss.hasPermission('person:user:query')")
    public CommonResult<PageResult<MemberUserRespVO>> getPresentationUserPage(@Valid MemberUserPageReqVO pageVO) {
        // 获取报告关联人员ID集合
        Set<Long> presentationPersonIdSet = getPresentationPersonIds(pageVO.getPresentationId());
        // 当"只看已选"且有数据时，限制查询ID列表并判断是否需要查询
        if (pageVO.getOnlyPresentation()) {
            if (presentationPersonIdSet.isEmpty()) {
                return success(PageResult.empty());
            }
            pageVO.setIdList(new ArrayList<>(presentationPersonIdSet));
        }
        // 查询分页数据并处理标签/分组
        PageResult<MemberUserRespVO> voPageResult = getProcessedPageResult(pageVO, presentationPersonIdSet, Collections.emptySet());

        // 设置报告关联标志
        voPageResult.getList().forEach(vo -> vo.setIsPresentationSetting(presentationPersonIdSet.contains(vo.getId())));

        return success(voPageResult);
    }

    @GetMapping("/warnPage")
    @Operation(summary = "获得预警人员分页")
    @PreAuthorize("@ss.hasPermission('person:user:query')")
    public CommonResult<PageResult<MemberUserRespVO>> getWarnUserPage(@Valid MemberUserPageReqVO pageVO) {
        // 获取预警关联人员ID集合
        Set<Long> warnPersonIdSet = getWarnConfigPersonIds(pageVO.getWarnConfigId());
        // 当"只看已选"且有数据时，限制查询ID列表并判断是否需要查询
        if (pageVO.getOnlyWarn()) {
            if (warnPersonIdSet.isEmpty()) {
                return success(PageResult.empty());
            }
            pageVO.setIdList(new ArrayList<>(warnPersonIdSet));
        }

        // 查询分页数据并处理标签/分组
        PageResult<MemberUserRespVO> voPageResult = getProcessedPageResult(pageVO, Collections.emptySet(), warnPersonIdSet);

        // 设置预警关联标志
        voPageResult.getList().forEach(vo -> vo.setIsWarnSetting(warnPersonIdSet.contains(vo.getId())));

        return success(voPageResult);
    }

    @GetMapping("/pageCase")
    @Operation(summary = "获得人员分页")
//    @PreAuthorize("@ss.hasPermission('person:user:query')")
    public CommonResult<PageResult<PersonCurInfoVo>> getUserCurInfoPage(@Valid MemberUserPageReqVO pageVO) {
        PageResult<MemberUserDO> pageResult = memberUserService.getUserCurInfoPage(pageVO);
        if (CollUtil.isEmpty(pageResult.getList())) {
            return success(PageResult.empty());
        }
        List<MemberUserDO> memberUserList = pageResult.getList();
        // 处理用户分组返显
        List<MemberGroupDO> groups = memberGroupService.getGroupList(
                convertSet(memberUserList, MemberUserDO::getGroupId));

        // 补充人员最后位置和对应的时间
        PageResult<PersonCurInfoVo> voPageResult = MemberUserConvert.INSTANCE.convertCurInfoPage(pageResult, groups);
        List<PersonCurInfoVo> userList = voPageResult.getList();
        Set<Integer> userIdSet = userList.stream().map(PersonCurInfoVo::getId).collect(Collectors.toSet());
        if (!userIdSet.isEmpty()) {
            List<LocationLastDO> userLastLocationList = locationLastService.listByIds(userIdSet);
            Map<Long, LocationLastDO> userMap = userLastLocationList.stream()
                    .collect(Collectors.toMap(
                            LocationLastDO::getId,  // 作为key的字段
                            Function.identity(),    // 作为value的对象本身
                            (existing, replacement) -> existing  // 出现重复key时保留第一个
                    ));
            List<PersonWarningCountDTO> personWarningCountDTOS = warningIndividualService.countPersonWarnings(new ArrayList<>(userIdSet));
            Map<Long, PersonWarningCountDTO> warnMap = personWarningCountDTOS.stream()
                    .collect(Collectors.toMap(
                            PersonWarningCountDTO::getPersonId,  // 作为key的字段
                            Function.identity(),    // 作为value的对象本身
                            (existing, replacement) -> existing  // 出现重复key时保留第一个
                    ));
            for (PersonCurInfoVo userRespVO : userList) {
                LocationLastDO locationLastDO = userMap.get(Long.parseLong(userRespVO.getId() + ""));
                if (locationLastDO != null) {
                    userRespVO.setLastLocation(locationLastDO.getAddress());
                    userRespVO.setLastLocationTime(LocalDateTimeUtil.format(locationLastDO.getLocationTime(), DatePattern.NORM_DATETIME_PATTERN));

                }
                PersonWarningCountDTO personWarningCountDTO = warnMap.get(Long.parseLong(userRespVO.getId() + ""));
                if (personWarningCountDTO != null) {
                    userRespVO.setReadTotal(personWarningCountDTO.getReadTotal());
                    userRespVO.setUnreadTotal(personWarningCountDTO.getUnreadTotal());
                    userRespVO.setWarnCount(personWarningCountDTO.getWarnCount());
                }
            }
        }
        return success(voPageResult);
    }

    @PostMapping("/import")
    @Operation(summary = "导入人员")
    @Parameters({
            @Parameter(name = "file", description = "Excel 文件", required = true),
            @Parameter(name = "updateSupport", description = "是否支持更新，默认为 false", example = "true")
    })
    @PreAuthorize("@ss.hasPermission('member:user:import')")
    public CommonResult<MemberImportRespVO> importExcel(@RequestParam("file") MultipartFile file,
                                                        @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport) throws Exception {
        List<MemberImportExcelVO> list = ExcelUtils.read(file, MemberImportExcelVO.class);
        return success(memberUserService.importUserList(list, updateSupport));
    }

    @Operation(summary = "删除人员")
    @DeleteMapping("/deleteUser")
    @PreAuthorize("@ss.hasPermission('member:user:delete')")
    public CommonResult<Boolean> deleteUser(@RequestParam("id") Long id) {
        return success(memberUserService.deleteUser(id));
    }

    @GetMapping("/get-import-template")
    @Operation(summary = "获得导入用户模板")
    public void importTemplate(HttpServletResponse response) throws IOException {
        // 手动创建导出 demo
        List<MemberImportExcelVO> list = Collections.singletonList(
                MemberImportExcelVO.builder().name("张三丰").idcard("330111199809123425").foreigner(YesNoEnum.YES.getYesNo()).phoneNumber("15601691300")
                        .country("中国").nation("汉族").sex(SexEnum.MALE.getSex()).liveAddress("浙江省宁波市裕阳路4号").birthPlace("浙江省宁波市裕阳路4号").build()
        );
        // 输出
        ExcelUtils.write(response, "用户导入模板.xls", "用户列表", MemberImportExcelVO.class, list);
    }


    /**
     * 获取案件关联人员ID集合
     */
    private Set<Long> getCasePersonIds(String caseId) {
        if (StrUtil.isEmpty(caseId)) {
            return Collections.emptySet();
        }
        Set<Long> result = casePersonRelationService.getCasePersonRelation(caseId);
        return result == null ? Collections.emptySet() : result;
    }

    /**
     * 获取案件关联人员ID集合
     */
    private Set<Long> getPresentationPersonIds(Long presentationId) {
        if (presentationId == null) {
            return Collections.emptySet();
        }
        Set<Long> result = presentationPersonRelationService.getPresentationPersonIds(presentationId);
        return result == null ? Collections.emptySet() : result;
    }

    /**
     * 获取预警关联人员ID集合
     */
    private Set<Long> getWarnConfigPersonIds(String warnConfigId) {
        if (warnConfigId == null) {
            return Collections.emptySet();
        }
        Set<Long> result = warnConfigPersonRelationService.getWarnConfigPersonRelationByWarnConfigId(warnConfigId);
        return result == null ? Collections.emptySet() : result;
    }

    /**
     * 当"只看已选"且有数据时，设置查询ID列表并判断是否需要继续查询
     *
     * @return true-需要继续查询，false-无需查询（直接返回空结果）
     */
    private boolean setIdListIfNeeded(MemberUserPageReqVO pageVO, Set<Long> personIdSet) {
        if (pageVO.getOnlyWarn() && !personIdSet.isEmpty()) {
            pageVO.setIdList(new ArrayList<>(personIdSet));
            // 当只看已选且有数据时，无需查询（已通过ID列表过滤）
            return true;
        }
        // 需要继续查询
        return false;
    }

    /**
     * 查询分页数据并处理标签、分组转换
     */
    private PageResult<MemberUserRespVO> getProcessedPageResult(MemberUserPageReqVO pageVO,
                                                                Set<Long> casePersonIdSet,
                                                                Set<Long> warnPersonIdSet) {
        PageResult<MemberUserDO> pageResult = memberUserService.getUserPage(pageVO);
        if (CollUtil.isEmpty(pageResult.getList())) {
            return PageResult.empty();
        }

        List<MemberUserDO> memberUserList = pageResult.getList();
        // 处理用户标签
        List<MemberTagDO> tags = getTagsByUserList(memberUserList);
        // 处理用户分组
        List<MemberGroupDO> groups = getGroupsByUserList(memberUserList);
        // 转换为VO并返回
        return MemberUserConvert.INSTANCE.convertPage(pageResult, tags, groups);
    }

    /**
     * 根据用户列表获取关联的标签
     */
    private List<MemberTagDO> getTagsByUserList(List<MemberUserDO> userList) {
        Set<Long> tagIds = userList.stream()
                .map(MemberUserDO::getTagIds)
                .filter(Objects::nonNull)
                .flatMap(Collection::stream)
                .collect(Collectors.toSet());
        return memberTagService.getTagList(tagIds);
    }

    /**
     * 根据用户列表获取关联的分组
     */
    private List<MemberGroupDO> getGroupsByUserList(List<MemberUserDO> userList) {
        Set<Long> groupIds = convertSet(userList, MemberUserDO::getGroupId);
        return memberGroupService.getGroupList(groupIds);
    }
}
